"""
Copyright (C) 2009 Attila-Mihaly Balazs

TwitFeeder is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

TwitFeeder is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU Affero General Public License
along with TwitFeeder.  If not, see <http://www.gnu.org/licenses/>
"""
import os
import logging
import urllib
import traceback
import sys
import random
import string
from google.appengine.ext.webapp import template
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from workhorse import StatusFetcher, get_base_url
from datetime import datetime, timedelta

def get_user_uniqueid(req):
    """
    Checks if the request has the "uniqid" cookie set and returns it.
    Otherwise sets it. This will be used later to gather statistics
    """
    uid = req.request.cookies.get('uniqid')
    if uid: return uid
    uid = ''.join(random.sample(string.letters+string.digits, 8))
    req.response.headers.add_header('Set-Cookie',
        'uniqid=%s; expires=Fri, 31-Dec-2020 23:59:59 GMT' % uid.encode())
    return uid

class ErrorCatcherHandler(webapp.RequestHandler):
    def handle_exception(self, exception, debug_mode):
        trace = traceback.format_exception(*sys.exc_info())
        logging.error(''.join(trace))
        if debug_mode:
            self.error(500)
            self.response.headers['Content-Type'] = 'text/plain'
            self.response.out.write(''.join(trace))
        else:
            self.redirect("/?error=1")

class AvatarImage(ErrorCatcherHandler):
    def get(self, baseUrl, userName):
        try:
            avatarData = StatusFetcher.find_user_image(userName, baseUrl)
            self.response.headers['Content-Type']  = 'image/png'
            expiry_time = datetime.now() + timedelta(seconds=StatusFetcher.user_image_timeout)
            self.response.headers['Expires']       = expiry_time.strftime("%a, %d %b %Y %H:%M:%S %Z")
            self.response.headers['Cache-Control'] = 'public, max-age=%d' % StatusFetcher.user_image_timeout
            self.response.out.write(avatarData)
        except Exception:
            self.redirect('/static/unknown_user.png')

class FeedPage(webapp.RequestHandler):
    def get(self, uniqId, baseUrl, userName):
        userName = urllib.unquote_plus(userName)
        feed = StatusFetcher.fetch_feed(userName, baseUrl)
        path = os.path.join(os.path.dirname(__file__), 'templates/feed.xml')
        self.response.headers['Content-Type'] = 'application/rss+xml; charset=utf-8'
        self.response.out.write(template.render(path, {
            'feed'       : feed,
            'username'   : userName,
            'base_url'   : baseUrl,
            'uniqid'     : uniqId,
            'root_url'   : get_base_url(),
            'is_hashtag' : feed['is_hashtagfeed'],
        }))
    
    # for feeds we don't do the actual redirection, since the feed reader might
    # not understand HTML
    def handle_exception(self, exception, debug_mode):
        logging.error(exception)
        self.error(500)
    
class HtmlPage(ErrorCatcherHandler):
    def get(self, baseUrl, userName):
        userName = urllib.unquote_plus(userName)
        uid = get_user_uniqueid(self)
        feed = StatusFetcher.fetch_feed(userName, baseUrl)
        path = os.path.join(os.path.dirname(__file__), 'templates/htmlfeed.html')
        self.response.out.write(template.render(path, {
            'feed'       : feed,
            'username'   : userName,
            'base_url'   : baseUrl,
            'uniqid'     : uid,
            'root_url'   : get_base_url(),
            'is_hashtag' : feed['is_hashtagfeed'],
        }))

class StaticPage(ErrorCatcherHandler):
    def get(self):
        path = os.path.join(os.path.dirname(__file__), 'templates' + self.request.path +'.html')
        self.response.out.write(template.render(path, {}))

# we can get into an infinite loop here due to redirection, but browsers should
# stop after 5 redirects
class MainPage(ErrorCatcherHandler):
    def get(self):
        get_user_uniqueid(self)
        error = self.request.get('error')
        path  = os.path.join(os.path.dirname(__file__), 'templates/index.html')
        self.response.out.write(template.render(path, { 'error' : error }))

    def post(self):
        get_user_uniqueid(self)
        id = self.request.get('id')
        if not id: self.redirect('/')
        (baseUrl, userName) = StatusFetcher.extract_url_parts(id)
        self.redirect("/html/" + baseUrl + "/" + urllib.quote(userName))

application = webapp.WSGIApplication([
    ('/', MainPage),
    ('/feed/(\w+)/(.+)/(' + StatusFetcher.partial_re_twt_user_urlencoded + ')', FeedPage),
    ('/html/(.+)/(' + StatusFetcher.partial_re_twt_user_urlencoded + ')', HtmlPage),
    ('/avatar/(.+)/(' + StatusFetcher.partial_re_twt_user_urlencoded + ')', AvatarImage),
    ('^/(?:supportus|contactus)$', StaticPage)],
    debug=True)

def main():
    logging.getLogger().setLevel(logging.DEBUG)
    run_wsgi_app(application)

if __name__ == "__main__":
    main()
